﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AddIn.EA.Framework;
using AddIn.EA.Framework.Common;
using System.Runtime.Serialization;
using System.Xml.Serialization;

namespace AddIn.EA.Architecture.ComponentLogic
{
    [Serializable()]
    public class BusinessEntity : ISerializable
    {
        #region Property
        [XmlElement("Name")]
        public string Name { get; set; }
        [XmlElement("Notes")]
        public string Notes { get; set; }
        [XmlElement("Stereotype")]
        public string Stereotype { get; set; }
        [XmlElement("Scope")]
        public ElementScope Scope { get; set; }
        [XmlElement("HasFilter")]
        public bool HasFilter { get; set; }
        [XmlElement("HasKeyFilter")]
        public bool HasKeyFilter { get; set; }
        [XmlElement("Properties")]
        public virtual List<Property> Properties { get; set; }
        #endregion

        public void Update(Package bePackage)
        {
            // Cria o elemento Class do EA e atribui os valores da entidade
            Element businessEntity = bePackage.Elements.AddNew(this.Name, ElementType.Class);
            businessEntity.Notes = this.Notes;
            businessEntity.Stereotype = this.Stereotype;
            businessEntity.Update();

            if (this.Stereotype != "ProcessEntity")
            {
                // Adiciona classe base
                businessEntity.AddBaseClass(string.Format("Base{0}", this.Stereotype));
                businessEntity.Update();
            }

            if (this.Properties != null && this.Properties.Count > 0)
            {
                // Adiciona as propriedades
                foreach (Property property in this.Properties)
                    property.Update(businessEntity);

                // Atualiza lista de elementos filhos do elemento.
                businessEntity.Refresh();
            }

            // Cria os parametros para entidade de filtro
            if(this.HasFilter)
                CreateEntityParameter(bePackage);

            // Cria os parametros para entidade de filtro por chave
            if(this.HasKeyFilter)
                CreateKeyParameter(bePackage);

        }

        private void CreateEntityParameter(Package bePackage)
        {
            // Obter a package parameter
            Package parameter = bePackage.GetPackageByName("Parameter");
            
            if (parameter == null)
                parameter = bePackage.Packages.AddNew("Parameter");

            parameter.Update();

            // Cria o elemento Class do EA e atribui os valores da entidade
            Element businessEntity = parameter.Elements.AddNew(string.Format("Filtro{0}", this.Name), ElementType.Class);
            businessEntity.Notes = string.Format("Filtro para {0}", this.Name);
            businessEntity.Stereotype = this.Stereotype;
            businessEntity.Update();

            // Adiciona classe base
            if (this.Properties != null && this.Properties.Count > 0 && CheckAllPropertiesAreFilter())
                businessEntity.AddBaseClass(string.Format("{0}.{1}", this.Stereotype, this.Name));
            else
                businessEntity.AddBaseClass(string.Format("Base{0}", this.Stereotype));

            businessEntity.Update();

            if (this.Properties != null && this.Properties.Count > 0 && !CheckAllPropertiesAreFilter())
            {
                // Adiciona as propriedades
                foreach (Property property in this.Properties)
                {
                    if (property.ComposeFilter)
                        property.Update(businessEntity);
                }

                // Atualiza lista de elementos filhos do elemento.
                businessEntity.Refresh();
            }

            bePackage.Update();
        }

        private void CreateKeyParameter(Package bePackage)
        {
            // Obter a package parameter
            Package parameter = bePackage.GetPackageByName("Parameter");

            if (parameter == null)
                parameter = bePackage.Packages.AddNew("Parameter");
            
            parameter.Update();

            // Cria o elemento Class do EA e atribui os valores da entidade
            Element businessEntity = parameter.Elements.AddNew(string.Format("Filtro{0}Chave", this.Name), ElementType.Class);
            businessEntity.Notes = string.Format("Filtro chave para {0}", this.Name);
            businessEntity.Stereotype = this.Stereotype;
            businessEntity.Update();

            // Adiciona classe base
            businessEntity.AddBaseClass(string.Format("Base{0}", this.Stereotype));
            businessEntity.Update();

            if (this.Properties != null && this.Properties.Count > 0)
            {
                // Adiciona as propriedades
                foreach (Property property in this.Properties)
                {
                    if (property.ComposeKey)
                        property.Update(businessEntity);
                }

                // Atualiza lista de elementos filhos do elemento.
                businessEntity.Refresh();
            }

            bePackage.Update();
        }

        private bool CheckAllPropertiesAreFilter()
        {
            return (this.Properties.FindAll(property => !property.ComposeFilter).Count == 0);
        }

        #region ISerializable Members

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}

